package com.rickpan.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import com.rickpan.config.RabbitMQConfig;
import com.rickpan.service.TeamMemberService;
import com.rickpan.entity.TeamMember;

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

/**
 * 消息队列服务类
 * 提供队列管理、消息发送等核心功能
 *
 * @author 开发团队协调员
 * @since 2025-07-17
 */
@Service
@ConditionalOnProperty(name = "spring.rabbitmq.host", matchIfMissing = false)
public class MessageQueueService {

    private static final Logger logger = LoggerFactory.getLogger(MessageQueueService.class);

    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Autowired
    private RabbitAdmin rabbitAdmin;
    
    @Autowired
    private DirectExchange teamDirectExchange;
    
    @Autowired
    private TopicExchange teamTopicExchange;
    
    @Autowired
    private FanoutExchange teamFanoutExchange;

    @Autowired
    private TeamMemberService teamMemberService;

    // 缓存已创建的队列，避免重复创建
    private final Map<String, Boolean> queueCache = new ConcurrentHashMap<>();
    
    // ==================== 队列管理 ====================
    
    /**
     * 确保团队消息队列存在
     * 如果队列不存在则创建
     * 
     * @param teamId 团队ID
     */
    public void ensureTeamMessageQueue(Long teamId) {
        String queueName = "team.message." + teamId;
        
        if (queueCache.containsKey(queueName)) {
            return; // 队列已存在
        }
        
        try {
            // 创建队列
            Queue queue = RabbitMQConfig.createTeamMessageQueue(teamId);
            rabbitAdmin.declareQueue(queue);
            
            // 创建绑定
            Binding binding = RabbitMQConfig.createTeamMessageBinding(teamId, queue, teamDirectExchange);
            rabbitAdmin.declareBinding(binding);
            
            // 缓存队列状态
            queueCache.put(queueName, true);
            
            logger.info("✅ 团队消息队列创建成功: {}", queueName);
            
        } catch (Exception e) {
            logger.error("❌ 团队消息队列创建失败: {}", queueName, e);
            throw new RuntimeException("队列创建失败", e);
        }
    }
    
    /**
     * 确保用户通知队列存在
     * 
     * @param userId 用户ID
     */
    public void ensureUserNotificationQueue(Long userId) {
        String queueName = "user.notification." + userId;
        
        if (queueCache.containsKey(queueName)) {
            return; // 队列已存在
        }
        
        try {
            // 创建队列
            Queue queue = RabbitMQConfig.createUserNotificationQueue(userId);
            rabbitAdmin.declareQueue(queue);
            
            // 绑定到Direct Exchange（用于精确通知）
            Binding directBinding = BindingBuilder
                    .bind(queue)
                    .to(teamDirectExchange)
                    .with("user." + userId + ".notification");
            rabbitAdmin.declareBinding(directBinding);
            
            // 绑定到Fanout Exchange（用于广播通知）
            Binding fanoutBinding = BindingBuilder
                    .bind(queue)
                    .to(teamFanoutExchange);
            rabbitAdmin.declareBinding(fanoutBinding);
            
            // 缓存队列状态
            queueCache.put(queueName, true);
            
            logger.info("✅ 用户通知队列创建成功: {}", queueName);
            
        } catch (Exception e) {
            logger.error("❌ 用户通知队列创建失败: {}", queueName, e);
            throw new RuntimeException("队列创建失败", e);
        }
    }
    
    // ==================== 消息发送 ====================
    
    /**
     * 发送团队消息到队列（简化版本）
     * 阶段1：直接发送到团队队列，不使用用户队列
     *
     * @param teamId 团队ID
     * @param message 消息对象
     */
    public void sendTeamMessageSimple(Long teamId, Object message) {
        try {
            logger.info("📤 发送消息到团队队列（简化模式）: teamId={}", teamId);

            // 直接发送到团队队列
            String queueName = "team.message." + teamId;
            rabbitTemplate.convertAndSend(queueName, message);

            logger.info("✅ 团队消息发送成功: teamId={}, queue={}", teamId, queueName);

        } catch (Exception e) {
            logger.error("❌ 团队消息发送失败: teamId={}", teamId, e);
            throw new RuntimeException("消息发送失败", e);
        }
    }

    /**
     * 发送团队消息到队列（复杂版本 - 暂时禁用）
     * 使用用户队列和Fanout Exchange的复杂架构
     *
     * @param teamId 团队ID
     * @param message 消息对象
     */
    public void sendTeamMessage(Long teamId, Object message) {
        try {
            logger.info("⚠️ 复杂RabbitMQ广播暂时禁用，使用简化版本: teamId={}", teamId);
            // 暂时调用简化版本
            sendTeamMessageSimple(teamId, message);

            // TODO: 修复RabbitMQ用户队列消费者问题后重新启用
            /*
            // 获取团队所有成员
            List<Long> teamMemberIds = getTeamMemberIds(teamId);

            if (teamMemberIds.isEmpty()) {
                logger.warn("⚠️ 团队无成员，跳过消息发送: teamId={}", teamId);
                return;
            }

            // 确保所有团队成员的用户队列存在
            for (Long userId : teamMemberIds) {
                ensureUserNotificationQueue(userId);
            }

            // 使用Fanout Exchange广播消息到所有用户队列
            rabbitTemplate.convertAndSend(
                teamFanoutExchange.getName(),
                "", // Fanout Exchange不需要routing key
                message
            );

            logger.info("📤 团队消息广播成功: teamId={}, memberCount={}", teamId, teamMemberIds.size());
            */

        } catch (Exception e) {
            logger.error("❌ 团队消息处理失败: teamId={}", teamId, e);
            throw new RuntimeException("消息处理失败", e);
        }
    }

    /**
     * 获取团队成员ID列表
     *
     * @param teamId 团队ID
     * @return 成员ID列表
     */
    private List<Long> getTeamMemberIds(Long teamId) {
        try {
            // 调用团队成员服务获取成员列表，然后提取用户ID
            List<TeamMember> teamMembers = teamMemberService.getTeamMembers(teamId);
            List<Long> memberIds = teamMembers.stream()
                    .map(TeamMember::getUserId)
                    .collect(java.util.stream.Collectors.toList());
            logger.debug("🔍 获取团队成员: teamId={}, memberCount={}", teamId, memberIds.size());
            return memberIds;
        } catch (Exception e) {
            logger.error("❌ 获取团队成员失败: teamId={}", teamId, e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 发送用户通知消息
     * 
     * @param userId 用户ID
     * @param message 通知消息
     */
    public void sendUserNotification(Long userId, Object message) {
        // 确保队列存在
        ensureUserNotificationQueue(userId);
        
        String routingKey = "user." + userId + ".notification";
        
        try {
            rabbitTemplate.convertAndSend(
                teamDirectExchange.getName(),
                routingKey,
                message
            );
            
            logger.info("📤 用户通知发送成功: userId={}, routingKey={}", userId, routingKey);
            
        } catch (Exception e) {
            logger.error("❌ 用户通知发送失败: userId={}, routingKey={}", userId, routingKey, e);
            throw new RuntimeException("通知发送失败", e);
        }
    }
    
    /**
     * 发送系统广播消息
     * 
     * @param message 广播消息
     */
    public void sendSystemBroadcast(Object message) {
        try {
            rabbitTemplate.convertAndSend(
                teamFanoutExchange.getName(),
                "", // Fanout Exchange不需要路由键
                message
            );
            
            logger.info("📤 系统广播发送成功");
            
        } catch (Exception e) {
            logger.error("❌ 系统广播发送失败", e);
            throw new RuntimeException("广播发送失败", e);
        }
    }
    
    /**
     * 发送文件上传进度消息
     * 
     * @param message 进度消息
     */
    public void sendFileUploadProgress(Object message) {
        try {
            rabbitTemplate.convertAndSend(
                "file.upload.progress",
                message
            );
            
            logger.debug("📤 文件上传进度发送成功");
            
        } catch (Exception e) {
            logger.error("❌ 文件上传进度发送失败", e);
            throw new RuntimeException("进度消息发送失败", e);
        }
    }
    
    // ==================== 主题消息发送 ====================
    
    /**
     * 发送主题消息
     * 支持基于消息类型的路由
     * 
     * @param teamId 团队ID
     * @param messageType 消息类型 (text/image/file)
     * @param message 消息对象
     */
    public void sendTopicMessage(Long teamId, String messageType, Object message) {
        String routingKey = "team." + teamId + "." + messageType;
        
        try {
            rabbitTemplate.convertAndSend(
                teamTopicExchange.getName(),
                routingKey,
                message
            );
            
            logger.info("📤 主题消息发送成功: teamId={}, messageType={}, routingKey={}", 
                       teamId, messageType, routingKey);
            
        } catch (Exception e) {
            logger.error("❌ 主题消息发送失败: teamId={}, messageType={}, routingKey={}", 
                        teamId, messageType, routingKey, e);
            throw new RuntimeException("主题消息发送失败", e);
        }
    }
    
    // ==================== 队列状态查询 ====================
    
    /**
     * 检查队列是否存在
     * 
     * @param queueName 队列名称
     * @return 是否存在
     */
    public boolean isQueueExists(String queueName) {
        try {
            QueueInformation queueInfo = rabbitAdmin.getQueueInfo(queueName);
            return queueInfo != null;
        } catch (Exception e) {
            logger.warn("⚠️ 检查队列状态失败: {}", queueName, e);
            return false;
        }
    }
    
    /**
     * 获取队列消息数量
     * 
     * @param queueName 队列名称
     * @return 消息数量
     */
    public int getQueueMessageCount(String queueName) {
        try {
            QueueInformation queueInfo = rabbitAdmin.getQueueInfo(queueName);
            return queueInfo != null ? queueInfo.getMessageCount() : 0;
        } catch (Exception e) {
            logger.warn("⚠️ 获取队列消息数量失败: {}", queueName, e);
            return 0;
        }
    }
    
    /**
     * 清空队列缓存
     * 用于重新检测队列状态
     */
    public void clearQueueCache() {
        queueCache.clear();
        logger.info("🧹 队列缓存已清空");
    }

    /**
     * 获取所有团队消息队列名称
     * 供@RabbitListener动态监听使用
     *
     * @return 队列名称数组
     */
    public String[] getAllTeamMessageQueues() {
        try {
            // 阶段2：动态获取所有活跃团队的队列
            // 这里可以从数据库查询所有活跃团队，但为了简化，先返回一些常用队列
            List<String> queueNames = new ArrayList<>();

            // 添加已知的团队队列（可以从数据库动态获取）
            for (long teamId = 1; teamId <= 10; teamId++) {
                String queueName = "team.message." + teamId;
                queueNames.add(queueName);
                // 确保队列存在
                ensureTeamMessageQueue(teamId);
            }

            String[] queues = queueNames.toArray(new String[0]);
            logger.info("📋 动态队列列表: {}", Arrays.toString(queues));
            return queues;

        } catch (Exception e) {
            logger.error("❌ 获取团队队列列表失败", e);
            // 返回默认队列，确保系统能正常工作
            return new String[]{"team.message.4"};
        }
    }
}
